#include"Task.hpp"
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
#include<assert.h>
#include<time.h>

vector<task_t> tasks;
int channel_num=5;

struct channel{
    public:
    channel(int fd,int id,string name)
    :_fd(fd),_id(id),_name(name)
    {}
    public:
    int _fd;           //文件id
    pid_t _id;         //线程id
    string _name;      //线程名字
};
void slave(){
    while(true){
        int cmdcode;
        int n=read(0,&cmdcode,sizeof(int));
        if(n==sizeof(int)){
            cout<<"slaver say@ get a task: "<<getpid()<<" code: "<<cmdcode+1<<endl;
            tasks[cmdcode]();
        }
        if(n==0) break;
    }
}
void InitPool(vector<channel>& channels){
    for(int i=0;i<channel_num;i++){
        int pipefd[2]={0};
        int n=pipe(pipefd);
        assert(!n);
        (void)n;     //这行的作用是防止后面没有使用n，而发出未使用定义变量n的警告（有些编译器会出现）
        
        pid_t id=fork();
        if(id<0){
            perror("fork error\n");
        }else if(id==0){
            //child
            close(pipefd[1]);
            dup2(pipefd[0],0);
            close(pipefd[0]);
            slave();
            cout<<"process-"<<to_string(i)<<" exit"<<endl;
            exit(0);
        }else{
            //father
            close(pipefd[0]);
            channels.push_back(channel(pipefd[1],id,"channel-"+to_string(i)));
        }
    }
}
void Debug(vector<channel>& channels){
    for(auto it:channels){
        cout<<"fd: "<<it._fd<<"  id: "<<it._id<<"  name: "<<it._name<<endl;
    }
}
void CtrlprocessPool(vector<channel> channels){
    for(int i=0;i<5;i++){
        //随机选择任务和进程
        int cmdcode=rand()%tasks.size();
        int processnum=rand()%channels.size();

        ssize_t n=write(channels[processnum]._fd,&cmdcode,sizeof(cmdcode));
        sleep(1);
    }
}
void QuitPool(vector<channel>& channels){
    for(int i=0;i<channels.size();i++) close(channels[i]._fd);
    sleep(5);
    for(int i=0;i<channels.size();i++) waitpid(channels[i]._id,nullptr,0);
}
int main()
{
    Loadtask(&tasks);
    vector<channel> channels;
    srand(time(nullptr)^getpid()^1024);
    //初始化
    InitPool(channels);
    Debug(channels);

    //控制任务分配工作
    CtrlprocessPool(channels);
    
    //退出整个过程
    QuitPool(channels);

    return 0;
}